package ija.controller.replay;

import ija.xls.notation.GameMove;

import java.util.ArrayList;

/**
 * Trida reprezentuje vstupni seznam pohybu hry pro prehravac. Umoznuje ziskavat
 * aktualni(nasledujici) a predchozi pozici, pridavat pohyby, pracovat s indexi.
 * 
 * @author Radek Necas, xnecas18
 */
public class ReplayMoves {

    ArrayList<GameMove> allMoves;
    int index;
    int breakpoint;

    /**
     * Konstruktor vytvari novou instanci s prazdnymi hodnotami.
     */
    public ReplayMoves() {
        this.allMoves = new ArrayList();
        this.index = 0;
        this.breakpoint = -1;
    }

    /**
     * Metoda prida dalsi herni tah na konec seznamu.
     * 
     * @param gm
     */
    public void addGameMove(GameMove gm) {
        this.allMoves.add(gm);
    }

    /**
     * Metoda vycisti objekt. Seznam tahu bude vyprazdnen, index a breakpoint
     * nastaven na vychozi hodnoty.
     */
    public void clear() {
        this.allMoves.clear();
        this.index = 0;
        this.breakpoint = -1;
    }

    /**
     * Metoda vraci pocet vsech pohybu vcetne jiz provedenych, tedy velikost
     * celeho seznamu.
     * 
     * @return
     */
    public int getSize() {
        return this.allMoves.size();
    }

    /**
     * Vraci aktualni index. Pohyb na tomto indexu je vracen pri dalsim volani
     * getNextMove().
     * 
     * @return aktualni index
     */
    public int getIndex() {
        return this.index;
    }

    public int getRound() {
        return ((this.index + 1) / 2);
    }

    /**
     * Nastavi index na prislusnou hodnotu.
     * 
     * @param newIndex
     *            novy index
     * @return true pokud OK, jinak false (newIndex mimo meze)
     */
    public boolean setIndex(int newIndex) {
        if (newIndex < 0 || newIndex >= this.allMoves.size()) {
            return false;
        }

        this.index = newIndex;
        return true;
    }

    /**
     * Nastavi breakpoint na tah s prislusnym indexem
     * 
     * @param breakIndex
     *            index pro breakpoint
     * @return true OK, jinak false (breakIndex mimo meze)
     */
    public boolean setBreakpoint(int breakIndex) {
        if (breakIndex < 0 || breakIndex >= this.allMoves.size()) {
            return false;
        }

        this.breakpoint = breakIndex * 2;
        return true;
    }

    /**
     * Metoda odstrani breakpoint. Nastavi jej na vychozi hodnotu -1.
     */
    public void removeBreakPoint() {
        this.breakpoint = -1;
    }

    /**
     * 
     * @return pozice breakpointu
     */
    public int getBreakpoint() {
        return (this.breakpoint / 2);
    }

    /**
     * Metoda vraci dalsi tah v prubehu hry, tj. tah na ktery ukazuje index.
     * Metoda tah vrati a zvysi index o 1.
     * 
     * @return nasledujici(aktualni) tah nebo null
     */
    public GameMove getNextMove() {
        if (this.index < 0 || this.index >= this.allMoves.size()
                || (this.breakpoint > 0 && this.index >= this.breakpoint)) {
            return null;
        }

        GameMove gm = this.allMoves.get(this.index);
        this.index++;
        return gm;
    }

    /**
     * Metoda vraci predchozi tah prubehu hry. Snizi index o 1 a vrati tah, na
     * ktery ukazuje.
     * 
     * @return predchozi tah
     */
    public GameMove getPreviousMove() {
        if (this.index < 1 || this.index > this.allMoves.size()) {
            return null;
        }

        this.index--;
        return (this.allMoves.get(this.index));
    }
}
